<template>
  <div class="gis-layer-management">
    <div class="header">
      <div class="header-title">
        <span class="type-icon-name">
          <span class="header-name">数据图层</span>
        </span>
        <!-- 加载数据  -->
        <span v-show="!isLock" class="load-project-data" @click="openLoadLayer">
          <a-icon type="plus" />
          <span>加载数据</span>
        </span>
      </div>
    </div>
    <!-- 图层列表 -->
    <div class="layer-list four-scroll-y" @click="clearState">
      <draggable
        :list="layerList"
        :disabled="!enabled"
        class="list-group"
        v-bind="dragOptions"
        @start="enabled = true"
        @end="dragEnd"
      >
        <transition-group
          type="transition"
          :name="!enabled ? 'flip-list' : null"
        >
          <div
            v-for="layer in layerList"
            :key="layer.id"
            class="layer-item"
            @click.stop
            @drop.prevent.stop
          >
            <!-- @drop.prevent.stop 火狐浏览器打开新页面 -->
            <div
              class="layer-info-name"
              :class="{
                'layer-selected': selectLayerIdList.includes(layer.id),
              }"
              @click="($event) => clickLayerItem($event, layer)"
            >
              <!-- eyes -->
              <div
                class="layer-eyes icon-style"
                @click.stop="toggleShow(layer)"
              >
                <a-icon-font
                  :type="
                    layer.visible
                      ? 'iconicon-beifen3'
                      : 'icona-gailankaiqibeifen4'
                  "
                />
              </div>
              <!-- 折叠 -->
              <div
                class="folding-state icon-style"
                @click.stop="toggleFold(layer.id)"
              >
                <a-icon-font
                  :type="
                    layer.open ? 'iconicon-beifen' : 'iconicon-beifen-right'
                  "
                />
              </div>
              <!-- layer type icon and name -->
              <div
                class="layer-name"
                :class="{ 'edit-state': editLayerId === layer.id }"
              >
                <!-- layer type -->
                <div class="layer-type icon-style">
                  <a-icon-font :type="layerTypeIcon[layer.type]" />
                </div>
                <!--  正常状态 -->
                <div
                  v-if="editLayerId !== layer.id"
                  class="layer-name-text"
                  :title="layer.name"
                  @dblclick.stop="editLayerName(layer)"
                >
                  {{ layer.name }}
                </div>
                <!-- 编辑状态 -->
                <div v-else class="tabs-label-edit">
                  <a-input
                    v-model="activeEditLayerName"
                    v-focus
                    type="text"
                    size="small"
                    style="width: 100%;"
                    @pressEnter="($event) => $event.target.blur()"
                    @blur="($event) => editLayerNameCheck($event, layer)"
                  />
                </div>
              </div>
              <!-- 拖拽图层添加到地图 -->
              <a-tooltip
                v-if="editLayerId !== layer.id && !isLock"
                placement="top"
                :mouse-leave-delay="0.5"
              >
                <template slot="title">
                  <span>拖拽添加图层到地图</span>
                </template>
                <div
                  class="drag-layer-to-map"
                  :draggable="true"
                  @dragstart.stop="($event) => onLayerDragStart($event, layer)"
                >
                  <a-icon-font type="iconzengjia" />
                </div>
              </a-tooltip>
              <!-- 更多操作 -->
              <a-dropdown
                v-if="editLayerId !== layer.id"
                :placement="'bottomLeft'"
                :trigger="['click']"
              >
                <div
                  class="more-operations"
                  @click.stop="clickOrHoverDropdown(layer.id)"
                  @mouseenter="clickOrHoverDropdown(layer.id)"
                >
                  <a-icon-font type="icondiandian" />
                </div>
                <a-menu slot="overlay">
                  <a-menu-item
                    v-for="(action, index) in layerMoreOperations"
                    :key="index"
                    :disabled="action.disabled"
                  >
                    <div @click="layerAction(layer, action)">
                      {{ action.name }}
                    </div>
                  </a-menu-item>
                </a-menu>
              </a-dropdown>
            </div>
            <div
              v-show="openLayerList.includes(layer.id)"
              class="layer-content"
            >
              <div class="icon-style">
                <a-icon-font :type="'icontiaoxing2'" />
              </div>
              <div>next</div>
            </div>
          </div>
        </transition-group>
      </draggable>
    </div>

    <!-- 加载数据 -->
    <load-data-modal
      :visible="loadVisible"
      :project-id="projectId"
      :tab-id="currentTabId"
      :user-data-list="allGisData"
      :search-data-list="searchDataList"
      :btn-loading="btnLoading"
      type="gis"
      @to-data-import="toDataImport"
      @key-change="onKeywordChanged"
      @close="loadVisible = false"
      @confirm-import="dataImport"
    />
    <!-- <layer-import-popup
      :project-id="projectId"
      :tab-id="currentTabId"
      :load-visible="loadVisible"
      :data="allGisData"
      ok-text="确定"
      cancel-text="取消"
      centered
      @confirm="confirmLayerImport"
      @cancel="cancelLayerImport"
    >
    </layer-import-popup> -->
    <layer-export-popup
      :export-layer="exportLayer"
      :project-id="projectId"
      :tab-id="currentTabId"
      :load-visible="exportLayerModalVisible"
      @confirm="confirmLayerExport"
      @cancel="exportLayerModalVisible = false"
    />
  </div>
</template>

<script lang="ts">
/**
 * gis 图层管理
 */
import { Vue, Component, Prop, Watch } from 'vue-property-decorator'
import LayerImportPopup from '@/components/gis/popup/LayerImportPopup.vue'
import LayerExportPopup from '@/components/gis/popup/LayerExportPopup.vue'
import GisStore from '@/store/modules/gis'
import draggable from 'vuedraggable'
import { uniq } from 'lodash'
import checkEditName from '@/util/check-util'
import * as turf from '@turf/turf'
import mapUtils from '@/components/gis/map-package/map-utils'
import LoadDataModal from '@/components/Modal/LoadDataModal.vue'
import { queryUserDatalist } from '@/api/data-list'

@Component({
  components: {
    LayerImportPopup,
    LayerExportPopup,
    draggable,
    LoadDataModal,
  },
  directives: {
    focus: {
      inserted: (element: any) => {
        element.focus()
      },
    },
  },
})
export default class LayerManagement extends Vue {
  // 项目id
  @Prop({ type: Number, default: 0 }) projectId!: number
  @Prop({ type: Number }) currentTabId!: number //  当前 tabId
  @Prop({ type: Boolean, default: true }) isLock!: Boolean

  public loadVisible: boolean = false // 加载图层数据
  public allGisData: any = [] // 当前用户下所有 gis 数据
  public enabled: boolean = true // 拖拽禁用
  private editLayerId: string | number | null = null // 添加编辑功能
  private activeEditLayerName: string = '' // 编辑的 layer name
  public selectLayerIdList: any[] = [] // shift 选择的 图层
  public layerList: any = [] // 当前画布图层
  public openLayerList: number[] = [] // 展开的图层
  public exportLayer: any = null // 导出数据的图层
  public exportLayerModalVisible: boolean = false
  public btnLoading: boolean = false // 加载数据库按钮loading
  public searchDataList: Array<any> = [] // 加载数据搜索结果

  public layerTypeIcon: any = {
    fill: 'iconmian',
    line: 'iconxian',
    circle: 'icondian',
  }
  public get dragOptions() {
    return {
      animation: 200,
      group: 'description',
      disabled: false,
      ghostClass: 'ghost',
    }
  }
  // 图层列表
  public get storeLayerList(): any {
    return GisStore.layerList
  }
  public get selectLayer() {
    return GisStore.selectLayer
  }

  @Watch('selectLayer.id')
  public watchSelectLayerId(id: number) {
    this.selectLayerIdList = [id]
  }

  @Watch('storeLayerList', { deep: true })
  public watchLayerList() {
    this.$nextTick(() => {
      this.layerList = GisStore.layerList
        .map((layer: any) => {
          return { ...layer }
        })
        .sort((a: any, b: any) => {
          return a.order - b.order
        })
    })
  }

  @Watch('currentTabId', { immediate: true })
  public watchTabId() {
    this.clearState()
  }

  /**
   * 关键字搜索
   */
  private async onKeywordChanged(keyword: string, type: any) {
    const response = await queryUserDatalist({
      // const response = await searchUserDatalist({
      data: {
        content: keyword.trim(),
        projectId: this.projectId,
        type,
      },
    })
    const list: any = []
    response.data.result.forEach((group: any) => {
      group.dataset.forEach((item: any) => {
        list.push({
          title: `${item.name} (${group.categoryName})`,
          key: item.id,
          disableCheckbox: item.status === 1,
        })
      })
    })
    this.searchDataList = list
  }

  /**
   *  跳转到数据导入
   */
  public toDataImport() {
    // 保存当前的url
    const parameters: any = {
      url: `/project/${this.$route.params.id}/gis`,
      projectId: this.$route.params.id,
      tabId: this.currentTabId,
      loadType: 'gis',
    }
    sessionStorage.setItem('lastUrl', JSON.stringify(parameters))
    const { href } = this.$router.resolve({
      path: '/management/data/import',
    })
    window.location.href = href
  }

  /**
   * 加载导入的数据
   */
  public async dataImport(ids: number[]) {
    if (ids.length === 0) {
      this.$message.warning('请选择数据后确认!')
      return
    }
    const parameters: any = {
      projectId: this.projectId,
      tabId: this.currentTabId,
      datasetIds: ids,
    }
    this.btnLoading = true
    try {
      const response: any = await GisStore.loadGisDataToLayerManagement(
        parameters
      )
      this.btnLoading = false
      this.loadVisible = false
      if (response.data.code === 100) {
        if (Array.isArray(response.data.result)) {
          this.confirmLayerImport(response.data.result)
        } else {
          this.confirmLayerImport([response.data.result])
        }
      } else {
        this.$message.error('加载失败，请重新加载！')
      }
    } catch (error) {
      this.btnLoading = false
      throw new Error(error)
    }
  }

  /**
   * 拖拽结束
   */
  public async dragEnd() {
    // 更改图层顺序
    const orders: any = this.layerList.map((layer: any) => layer.id)
    const parameters: any = {
      projectId: this.projectId,
      tabId: this.currentTabId,
      orders,
    }
    await this.updateLayerListOrder(parameters)
    this.$nextTick(() => {
      this.$emit('layer-update', { type: 'order', value: this.layerList })
    })
  }

  /**
   * 拖拽结束更新图层层级
   */
  public async updateLayerListOrder(parameters: any) {
    // TODO 后续统一到保存
    // await GisStore.updateLayerListOrder(parameters)
    await GisStore.resetLayerOrder(parameters)
  }

  // 当前点击更多操作的图层
  public clickDropdownLayerId: any = null

  public clickOrHoverDropdown(layerId: number) {
    this.clickDropdownLayerId = layerId
  }

  // 图层操作
  public get layerMoreOperations() {
    if (
      this.selectLayerIdList.length > 1 &&
      this.selectLayerIdList.includes(this.clickDropdownLayerId)
    ) {
      return [
        { name: '删除', type: 'delete', disabled: false },
        { name: '合并图层', type: 'mergedLayer', disabled: true },
      ]
    }
    if (this.isLock) {
      return [
        { name: '查看数据', type: 'viewData', disabled: false },
        { name: '复位', type: 'reset', disabled: false },
        { name: '导出', type: 'export', disabled: false },
      ]
    }
    return [
      { name: '查看数据', type: 'viewData', disabled: false },
      { name: '复位', type: 'reset', disabled: false },
      { name: '重命名', type: 'rename', disabled: false },
      { name: '删除', type: 'delete', disabled: false },
      { name: '导出', type: 'export', disabled: false },
    ]
  }

  /**
   * 加载图层数据
   */
  public async openLoadLayer() {
    // const gisData: any[] = await GisStore.queryAllGisData()
    queryUserDatalist({
      data: { projectId: this.projectId, type: 'gis' },
    })?.then((response: any) => {
      if (response.data.code === 100) {
        this.allGisData = response.data.result
        // this.allGisData = []
        // response.data.result.forEach((group: any) => {
        //   const groupList: Array<any> = []
        //   if (group.dataset.length > 0) {
        //     group.dataset.forEach((item: any) => {
        //       groupList.push({
        //         title: item.name,
        //         key: item.id,
        //         disableCheckbox: item.status === 1 ,
        //       })
        //     })
        //   }
        //   this.allGisData.push({
        //     title: group.categoryName,
        //     key: String(group.categoryId),
        //     children: groupList,
        //   })
        // })

        this.loadVisible = true
      }
    })
  }

  /**
   * 载入成功
   */
  public confirmLayerImport(layer: any) {
    this.loadVisible = false
    this.$emit('layer-update', { type: 'load-layer', value: layer })
  }

  /**
   * 取消导入
   */
  public cancelLayerImport() {
    this.loadVisible = false
  }

  /**
   * 导出数据
   */
  public confirmLayerExport() {
    this.exportLayerModalVisible = false
    // window.open(`${baseURL}/task/download?taskId=${this.selectNode.id}`)
  }

  /**
   * 点击 layer item
   * @param $event
   * @param layer
   */
  public clickLayerItem($event: MouseEvent, layer: any) {
    if ($event.shiftKey) {
      const exist: number = this.selectLayerIdList.indexOf(layer.id)
      if (exist > -1) {
        this.selectLayerIdList.splice(exist, 1)
      } else {
        this.selectLayerIdList.push(layer.id)
      }
    } else {
      this.selectLayerIdList = [layer.id]
      GisStore.setSelectLayer(layer)
    }
  }

  /**
   * 图层的操作
   * @param layer
   * @param action
   */
  public layerAction(layer: any, action: any) {
    const { type, disabled } = action
    if (disabled) {
      return
    }
    switch (type) {
      // 合并图层
      case 'mergedLayer':
        break
      // 删除
      case 'delete':
        this.deleteLayers(layer)
        break
      // 查看数据
      case 'viewData':
        this.viewLayerData(layer)
        break
      // 复位
      case 'reset':
        this.resetByLayer(layer)
        break
      // 重命名
      case 'rename':
        this.editLayerName(layer)
        break
      // 导出
      case 'export':
        this.layerExport(layer)
        break
      default:
        break
    }
  }

  /**
   * 删除确认提示框
   * @param layer
   */
  public deleteLayers(layer: any) {
    let deleteLayersId: number[] = [layer.id]
    if (this.selectLayerIdList.includes(layer.id)) {
      deleteLayersId = uniq([layer.id, ...this.selectLayerIdList])
    }
    const deleteLayers: any[] = this.layerList.filter((layerItem: any) =>
      deleteLayersId.includes(layerItem.id)
    )
    const layersNameString: string = deleteLayers
      .map((item: any) => item.name)
      .toString()
    this.$confirm({
      title: `确定要删除：${layersNameString} ？`,
      okText: '确定',
      cancelText: '取消',
      centered: true,
      onOk: () => {
        this.handleDeleteLayers(deleteLayersId)
      },
    })
  }

  /**
   * 确认删除图层
   * @param deleteLayersId
   */
  public async handleDeleteLayers(deleteLayersId: any) {
    const parameters: any = {
      projectId: this.projectId,
      layerIds: deleteLayersId,
    }
    const response: any = await GisStore.deleteLayerById(parameters)
    if (response.data.code === 100) {
      mapUtils.clearMapLayersByLayers(GisStore.mapboxInstance, deleteLayersId)
      this.clearState()
    }
  }

  /**
   * 查看图层数据
   * @param layer
   */
  public viewLayerData(layer: any) {
    this.$nextTick(() => {
      GisStore.setSelectLayer(layer)
      this.selectLayerIdList = [layer.id]
    })
    GisStore.setViewDataLayerTime()
  }

  /**
   * 双击修改图层名称
   * @param layer
   */
  public editLayerName(layer: any) {
    this.editLayerId = layer.id
    this.activeEditLayerName = layer.name
    this.enabled = false
  }

  public layerExport(layer: any) {
    this.exportLayer = layer
    this.exportLayerModalVisible = true
  }

  /**
   * 修改图层名称校验
   * 1-正常， 2-全空字符串， 3-重名， 5-和原名相同， 4-空
   */
  public async editLayerNameCheck($event: any, layer: any) {
    const flag: string = checkEditName(
      layer,
      this.layerList,
      'id',
      'name',
      this.activeEditLayerName
    )
    switch (flag) {
      case 'pass':
        this.enabled = true
        await this.editLayerNameEnter(layer)
        break
      case 'space':
        this.$message.warn('名称不能全为空格')
        this.activeEditLayerName = layer.name
        $event.target.focus()
        break
      case 'repetition':
        this.$message.warn('该名称已存在')
        $event.target.focus()
        break
      case 'empty':
        this.$message.warn('名称不能为空')
        this.activeEditLayerName = layer.name
        $event.target.focus()
        break
      case 'no-change':
        this.enabled = true
        this.closeEditState()
        break
      default:
        break
    }
  }

  /**
   * 修改图层名称
   */
  public async editLayerNameEnter(layer: any) {
    const parameters: any = {
      id: layer.id,
      property: 'name',
      value: this.activeEditLayerName.trim(),
    }
    GisStore.updateLayerPropertyKey(parameters)
    const response = await GisStore.gisSaveTabInfoWithLayer()
    if (!response.data.success) {
      this.$message.error('图层名称修改失败！')
    }
    this.$message.success('图层名称修改成功！')
    this.closeEditState()
  }

  public closeEditState() {
    this.editLayerId = null
    this.activeEditLayerName = ''
  }

  /**
   * 图层显示状态
   * @param layer
   */
  public async toggleShow(layer: any) {
    const visible = layer.visible === 1 ? 0 : 1
    const layerInfo: any = {
      ...layer,
      visible,
    }
    this.$emit('layer-update', { type: 'show', value: layerInfo })
  }

  /**
   * 请求接口修改图层显示状态
   */
  public async editLayerSeen(layerId: number, visible: number) {
    const parameters: any = {
      id: layerId,
      property: 'visible',
      value: visible,
    }
    GisStore.updateLayerPropertyKey(parameters)
    await GisStore.gisSaveTabInfoWithLayer()
  }

  /**
   * 根据图层数据复位
   * @param layer
   * @private
   */
  private async resetByLayer(layer: any) {
    const currentLayerDataExist = !!GisStore.layerData[layer.id]
    if (!currentLayerDataExist) {
      await this.queryLayerDataByLayerId(layer.id)
    }
    const geoJson: any = GisStore.layerData[layer.id]
    const bounds: any[] = turf.bbox(geoJson.geojson)
    GisStore.mapboxInstance.fitBounds(bounds, { padding: 50 })
  }

  /**
   * 获取图层 geojson 数据 by layerId
   */
  public async queryLayerDataByLayerId(layerId: number) {
    const config = {
      parameters: {
        projectId: this.projectId,
        layerId,
      },
      tabId: this.currentTabId,
    }
    await GisStore.queryLayerDataById(config)
  }

  /**
   * 折叠
   * @param layerId
   */
  public toggleFold(layerId: any) {
    console.log(layerId)
    // if (this.openLayerList.includes(layerId)) {
    //   const index: number = this.openLayerList.indexOf(layerId)
    //   this.openLayerList.splice(index, 1)
    // } else {
    //   this.openLayerList.push(layerId)
    // }
  }

  /**
   * 图层拖拽的画布
   * @param $event
   * @param layer
   * @private
   */
  private onLayerDragStart($event: DragEvent, layer: any) {
    let dragColumnName = document.querySelector('#dragColumn') as HTMLElement
    if (!dragColumnName) {
      dragColumnName = document.createElement('div')
      dragColumnName.id = 'dragColumn'
      dragColumnName.style.position = 'fixed'
      dragColumnName.style.height = '44px'
      dragColumnName.style.width = '150px'
      dragColumnName.style.padding = '10px 5px'
      dragColumnName.style.textAlign = 'center'
      dragColumnName.style.color = '#5d637e'
      dragColumnName.style.fontSize = '14px'
      dragColumnName.style.fontWeight = '400'
      dragColumnName.style.letterSpacing = '#1px'
      dragColumnName.style.overflow = 'hidden'
      dragColumnName.style.textOverflow = 'ellipsis'
      dragColumnName.style.whiteSpace = 'nowrap'
      dragColumnName.style.backgroundColor = 'rgba(103, 113, 252, 0.3)'
      document.body.append(dragColumnName)
    }
    dragColumnName.innerHTML = layer.name
    const nodeData = `${layer.name}:${layer.id}:${layer.type}:${layer.visible}`
    $event.dataTransfer?.setDragImage(dragColumnName, 75, 22) // 设置拖放时图像
    $event.dataTransfer?.setData('layer', nodeData)
  }

  /**
   * 点击空白处 清空选择
   */
  public clearState() {
    this.selectLayerIdList = []
    GisStore.setSelectLayer(null)
  }
}
</script>

<style lang="less" scoped>
@import '@/styles/scroll-bar';

.gis-layer-management {
  height: 100%;

  // 头
  .header {
    height: 44px;
    line-height: 44px;
    padding: 0 16px;
    user-select: none;
    width: 100%;

    .header-title {
      align-items: center;
      color: #b1b1b1;
      display: flex;
      justify-content: space-between;
      // 数据源 算子  icon
      .type-icon-name {
        align-items: center;
        display: flex;
        font-size: 20px;

        .header-name {
          color: #5d637e;
          font-size: 14px;
          font-weight: 700;
          letter-spacing: 1px;
        }
      }

      // 加载数据  新增算子
      .load-project-data {
        align-items: center;
        background-color: #fff;
        border: 1px solid #5561ff;
        border-radius: 11px;
        color: #5561ff;
        cursor: pointer;
        display: flex;
        font-size: 14px;
        height: 22px;
        justify-content: center;
        line-height: 22px;
        padding: 0 5px;
        text-align: center;

        span {
          color: #5561ff;
          height: 22px;
        }

        &:hover {
          background-color: #6570ff;
          color: #fff;

          span {
            color: #fff;
          }
        }
      }
    }

    .name {
      color: #4b4b4b;
    }
  }

  .layer-list {
    height: calc(100% - 44px);
    overflow-y: auto;

    .flip-list-move {
      transition: transform 0.5s;
    }

    .no-move {
      transition: transform 0s;
    }

    .ghost {
      background: rgba(103, 113, 252, 0.1);
      opacity: 0.5;
    }

    .layer-item {
      align-items: center;
      cursor: pointer;
      min-height: 44px;

      //&:hover {
      //  .layer-info-name {
      //    background: rgba(103, 113, 252, 0.1);
      //  }
      //}

      // 所有 icon
      .icon-style {
        align-items: center;
        display: flex;
        font-size: 16px;
        height: 20px;
        justify-content: center;
        margin-right: 6px;
        width: 20px;
      }

      .layer-info-name {
        align-items: center;
        display: flex;
        height: 44px;
        padding: 0 16px;

        // type + name
        .layer-name {
          align-items: center;
          display: flex;
          width: calc(100% - 52px);

          .layer-name-text {
            color: #5d637e;
            font-size: 14px;
            font-weight: 400;
            letter-spacing: 1px;
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
            width: calc(100% - 26px);
          }

          .tabs-label-edit {
            width: calc(100% - 26px);
          }
        }

        // 更多操作
        .more-operations {
          display: none;
          height: 20px;
          text-align: center;
          width: 20px;
        }

        // 拖拽移动顺序
        .drag-layer-to-map {
          display: none;
          height: 20px;
          margin-right: 6px;
          text-align: center;
          width: 20px;
        }

        &:hover {
          .layer-name {
            width: calc(100% - 98px); // 更多操作 20px 拖拽 20px mr: 6px
          }

          .edit-state {
            width: calc(100% - 52px);
          }

          .drag-layer-to-map {
            display: inline-block;
          }

          .more-operations {
            display: inline-block;
          }
        }
      }

      .layer-content {
        align-items: center;
        display: flex;
        height: 44px;
        padding: 0 16px 0 68px;
      }
    }

    .layer-selected {
      background: rgba(103, 113, 252, 0.1);
    }

    .layer-empty {
      align-items: center;
      display: flex;
      flex-direction: column;
      justify-content: center;

      img {
        width: 50%;
      }
    }
  }
}
</style>
